﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Reflection;
using System.Threading.Tasks;
using OpenAiClient.Util.Models;

namespace OpenAiClient.Util.Hardware
{
    public static class ManagementHelper
    {
        /// <summary>
        /// 获取CPU ID列表
        /// </summary>
        /// <returns>CPU ID列表</returns>
        public static List<string> GetCpuIdList()
        {
            return GetPropertyValueList("win32_processor", "ProcessorId");
        }

        /// <summary>
        /// 异步获取CPU使用率
        /// </summary>
        /// <returns></returns>
        public static async Task<double> GetCpuUsageAsync()
        {
            try
            {
                using (var performanceCounter = new PerformanceCounter("Processor",
                           "% Processor Time", "_Total"))
                {
                    performanceCounter.NextValue();
                    await Task.Delay(100);
                    return performanceCounter.NextValue();
                }
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取主板ID列表
        /// </summary>
        /// <returns>主板ID列表</returns>
        public static List<string> GetBoardIdList()
        {
            return GetPropertyValueList("Win32_BaseBoard", "SerialNumber");
        }

        /// <summary>
        /// 获取硬盘ID列表
        /// </summary>
        /// <returns></returns>
        public static List<string> GetDiskIdList()
        {
            return GetPropertyValueList("Win32_DiskDrive", "Model");
        }

        /// <summary>
        /// 获取固定磁盘信息列表
        /// </summary>
        /// <returns>固定磁盘信息列表</returns>
        public static List<DiskInfo> GetFixedDiskInfoList()
        {
            //Fixed hard disk media
            return GetDiskInfoList().Where(t => t.MediaType.Contains("Fixed")).ToList();
        }

        /// <summary>
        /// 获取可移动磁盘信息列表
        /// </summary>
        /// <returns>可移动磁盘信息列表</returns>
        public static List<DiskInfo> GetRemovableDiskInfoList()
        {
            //Removable Media
            return GetDiskInfoList().Where(t => t.MediaType.Contains("Removable")).ToList();
        }

        /// <summary>
        /// 获取硬盘信息列表
        /// </summary>
        /// <returns>硬盘信息列表</returns>
        public static List<DiskInfo> GetDiskInfoList()
        {
            var diskInfoList = new List<DiskInfo>();
            var propertyList = typeof(DiskInfo).GetProperties()
                .Where(t => t.MemberType == MemberTypes.Property && t.CanRead && t.CanWrite)
                .ToList();
            var propertyNameList = propertyList
                .Select(t => t.Name)
                .ToList();
            var propertyValueDicList = GetPropertyValues("Win32_DiskDrive", propertyNameList);
            foreach (var propertyValueDic in propertyValueDicList)
            {
                var diskInfo = new DiskInfo();

                foreach (var propertyValue in propertyValueDic)
                {
                    var propertyInfo = propertyList.FirstOrDefault(t => t.Name == propertyValue.Key);
                    if (propertyInfo == null)
                    {
                        continue;
                    }

                    if (propertyInfo.PropertyType == typeof(int)) //int
                    {
                        var value = int.TryParse(propertyValue.Value, out var parseValue) ? parseValue : 0;
                        propertyInfo.SetValue(diskInfo, value);
                    }
                    else if (propertyInfo.PropertyType == typeof(long)) //long
                    {
                        var value = long.TryParse(propertyValue.Value, out var parseValue) ? parseValue : 0;
                        propertyInfo.SetValue(diskInfo, value);
                    }
                    else //string
                    {
                        propertyInfo.SetValue(diskInfo, propertyValue.Value);
                    }
                }

                diskInfoList.Add(diskInfo);
            }

            return diskInfoList;
        }

        /// <summary>
        /// 获取网卡MAC列表
        /// </summary>
        /// <returns>网卡MAC列表</returns>
        public static List<string> GetNetworkCardMacList()
        {
            var macList = new List<string>();
            var managementClass = new ManagementClass("Win32_NetworkAdapterConfiguration");
            using (var moc = managementClass.GetInstances())
            {
                foreach (var baseObject in moc)
                {
                    if (baseObject is ManagementObject managementObject)
                    {
                        try
                        {
                            if ((bool)managementObject["IPEnabled"])
                            {
                                //MacAddress
                                macList.Add($"{managementObject["MacAddress"]}");
                            }
                        }
                        catch (Exception)
                        {
                            //Do nothing
                        }
                    }
                }
            }

            return macList;
        }

        /// <summary>
        /// 获取内存总大小
        /// </summary>
        /// <returns>内存总大小</returns>
        public static int GetTotalMemorySize()
        {
            return GetMemorySizeList().Sum();
        }

        /// <summary>
        /// 获取可用内存大小
        /// </summary>
        /// <returns>可用内存大小</returns>
        public static int GetFreeMemorySize()
        {
            return GetFreeMemorySizeList().Sum();
        }

        /// <summary>
        /// 获取内存大小列表(单位：KB)
        /// </summary>
        /// <returns>内存大小列表(单位：KB)</returns>
        private static List<int> GetMemorySizeList()
        {
            var memorySizeList = new List<int>();
            var list = GetPropertyValueList("Win32_OperatingSystem", "TotalVisibleMemorySize");
            list.ForEach(t =>
            {
                var memorySize = int.TryParse(t, out var value) ? value : 0;
                memorySizeList.Add(memorySize);
            });

            return memorySizeList;
        }

        /// <summary>
        /// 获取可用内存大小列表(单位：KB)
        /// </summary>
        /// <returns>可用内存大小列表(单位：KB)</returns>
        private static List<int> GetFreeMemorySizeList()
        {
            var memorySizeList = new List<int>();
            var list = GetPropertyValueList("Win32_OperatingSystem", "FreePhysicalMemory");
            list.ForEach(t =>
            {
                var memorySize = int.TryParse(t, out var value) ? value : 0;
                memorySizeList.Add(memorySize);
            });

            return memorySizeList;
        }

        /// <summary>
        /// 获取属性值列表
        /// </summary>
        /// <param name="path">管理类路径</param>
        /// <param name="propertyName">属性名称</param>
        /// <returns>属性值列表</returns>
        public static List<string> GetPropertyValueList(string path, string propertyName)
        {
            var propertyValueList = new List<string>();
            var managementClass = new ManagementClass(path);
            using (var moc = managementClass.GetInstances())
            {
                foreach (var baseObject in moc)
                {
                    if (baseObject is ManagementObject managementObject)
                    {
                        propertyValueList.Add($"{managementObject[propertyName]}");
                    }
                }
            }

            return propertyValueList;
        }

        /// <summary>
        /// 获取属性字典列表
        /// </summary>
        /// <param name="path">管理类路径</param>
        /// <param name="propertyNameList">属性名称列表</param>
        /// <returns>属性字典列表</returns>
        public static List<Dictionary<string, string>> GetPropertyValues(string path, List<string> propertyNameList)
        {
            var propertyValueDicList = new List<Dictionary<string, string>>();
            var managementClass = new ManagementClass(path);
            using (var moc = managementClass.GetInstances())
            {
                foreach (var baseObject in moc)
                {
                    if (baseObject is ManagementObject managementObject)
                    {
                        var propertyValueDic = new Dictionary<string, string>();
                        foreach (var propertyName in propertyNameList)
                        {
                            try
                            {
                                var value = managementObject[propertyName];
                                AddOrUpdateValue(propertyValueDic, propertyName, $"{value}");
                            }
                            catch (Exception)
                            {
                                AddOrUpdateValue(propertyValueDic, propertyName, string.Empty);
                            }
                        }

                        propertyValueDicList.Add(propertyValueDic);
                    }
                }
            }

            return propertyValueDicList;
        }

        private static void AddOrUpdateValue(Dictionary<string, string> dic, string key, string value)
        {
            if (dic == null || string.IsNullOrWhiteSpace(key))
            {
                return;
            }

            if (dic.ContainsKey(key))
            {
                dic[key] = value;
            }
            else
            {
                dic.Add(key, value);
            }
        }
    }
}
